// This Adobe Illustrator script batches the Braille labeling process
// Requirements:
// 1. Image is "name.Resized.bmp"
// 2. The corresponding location file is "name.SelMBs.xml"
// 3. The corresponding label file is "name.Text.txt"
// 4. Files 1, 2, and 3 are in the same folder
// Note: Doesn't work recursively

// select folder with source files
var workFolder = Folder.selectDialog("Select work folder","~");

// select folder to save to
var targetFolder = Folder.selectDialog("Select target folder", "~");

// find images
if(workFolder != null)
{
	var bmpList = new Array();
	var bmpCount = 0;
	var fileList = workFolder.getFiles();
	for( i = 0; i <fileList.length; i++)
	{
		if(fileList[i] instanceof File)
		{
			filename = fileList[i].fsName;
			extension = getSubString(filename,null,".Resized.bmp");
			if(extension != null)
			{
				bmpList.push(fileList[i]);
				bmpCount++;
			}
		}
	}
}

// label each image
for (i = 0; i < bmpCount; i++)
{
	
	//create new "dummy" file
	var docRef = app.documents.add();
	var fileRef = bmpList[i];
	if (fileRef != null)
	{
	var image = docRef.placedItems.add();
	image.file = fileRef;
	}
	
	//new
	var fullName = fileRef.fsName;
	var baseName = getSubString(fullName, null,".Resized.bmp");
	
	// get the image dimensions
	var imgheight = image.height;
	var imgwidth = image.width;
	
	var scaleX;
	var scaleY;
	var imgRes;
	var screenRes = 72; //Seems unchangeable in Illustrator
	
	// close dummy
	docRef.close(SaveOptions.DONOTSAVECHANGES);
	docRef = null;
	image = null;
	
	var successOne;
	var successTwo;
	var justname = bmpList[i].name;
	
	// get the label info file
	// see requirements at top of the page
	var locationFile = new File(baseName+".SelMBs.xml");
	successOne = locationFile.open ("r","TEXT");
	if(!successOne)
	{
		alert("Cannot find xml location file for "+justname);
		locationFile = File.openDialog("Select location file for " + justname);
		if(locationFile == null) successOne = false;
		else successOne = locationFile.open ("r", "TEXT");
	}
	
	var textFile = new File(baseName+".SelLabelsNoBoxes.txt");
	successTwo = textFile.open("r","TEXT");
	if(!successTwo)
	{
		alert("Cannot find txt label file for "+justname);
		textFile = File.openDialog("Select text file for " + justname);
		if(textFile == null) successTwo = false;
		else successTwo = textFile.open ("r", "TEXT");
	}
	
	if(successOne && successTwo)
	{
		// get required info
		var text = locationFile.read();
		text = getSubString(text,"<LocationInformation>", "</LocationInformation>");
		var numlabels = parseInt(getSubString(text,"<NumLabels>", "</NumLabels>"));
		imgRes = parseFloat(getSubString(text,"<Resolution>", "</Resolution>"));
		scaleX = parseFloat(getSubString(text,"<ScaleX>", "</ScaleX>"))*screenRes/imgRes;
		scaleY = parseFloat(getSubString(text,"<ScaleY>", "</ScaleY>"))*screenRes/imgRes;

		// advance to next block of text
		text = getSubString(text, "</ScaleY>",null);

		// create new file with correct dimensions
		docRef = documents.add(DocumentColorSpace.RGB, imgwidth, imgheight);
		image = docRef.placedItems.add();
		image.file = fileRef;

		// lock image layer
		imglayer = docRef.layers[0];
		imglayer.name = "Bitmap Image";
		imglayer.locked = true;

		// create guide layer
		guidelayer = docRef.layers.add();
		guidelayer.name = "Guides";

		// define Braille character style
		var charStyle = docRef.characterStyles.add("Braille");
		var charAttr = charStyle.characterAttributes;
		charAttr.size = 29;
		charAttr.textFont = app.textFonts.getByName("Braille29");

		var label;
		var title;
		var x1;
		var y1;
		var x2;
		var y2;
		var angle;
		var alignment;

		var i2;

		// read each label and create at supposed position
		for( i2 = 0; i2 < numlabels; i2++) {

			label = getSubString(text,"<Label>", "</Label>");
			title = textFile.readln();
			x1 = parseInt(getSubString(label, "<x1>", "</x1>"));
			y1 = parseInt(getSubString(label, "<y1>", "</y1>"));
			x2 = parseInt(getSubString(label, "<x2>", "</x2>"));
			y2 = parseInt(getSubString(label, "<y2>", "</y2>"));
			alignment = parseInt(getSubString(label, "<Alignment>", "</Alignment>"));
			angle = parseFloat(getSubString(label, "<Angle>", "</Angle>"));

			drawGuide(guidelayer,x1,y1,x2,y2,scaleX,scaleY);

			createLabel(docRef, charStyle, title, x1, y1, x2, y2, alignment, angle, scaleX, scaleY);

			// advance to next block of text
			text = getSubString(text,"</Label>", null);

		}

		// set the guides to be not visible and locked
		guidelayer.visible = false;
		guidelayer.locked = true;

		locationFile.close();
		//textFile.close();
	}
	
	// save current image
	theName = fileRef.name
	properName = getSubString(theName,null,".Resized.bmp");
	toSave = new File(targetFolder.fsName+"\\"+properName+".AI");
	docRef.saveAs(toSave);
	//docRef.close();

	    
}

// create a text label
function createLabel(dref, style, title, x1, y1, x2, y2, alignment, angle, xfactor, yfactor)
{
	
	var textRef;
	var destLayerRef;
	var rangeRef;
	
	destLayerRef = dref.layers.add();
	destLayerRef.name = title;
		
	textRef = destLayerRef.textFrames.add();
	rangeRef = textRef.textRange;
	rangeRef.contents = title;
	style.applyTo(rangeRef);
	textRef.top = imgheight-(y1*yfactor); // Illustrator y-axis is inverse of TGA
	
	if(alignment == -1) textRef.left = x1*xfactor;
	else if(alignment == 1) textRef.left = (x2*xfactor) - textRef.width;
	else textRef.left = (((x1+x2)/2)*xfactor) - (textRef.width/2);
}

// create original label visual guide
function drawGuide(layer, x1, y1, x2, y2, xfactor, yfactor)
{
	var left = (x1*xfactor);
	var top = imgheight-(y1*yfactor)-2;
	var width = (x2-x1)*xfactor;
	var height = (y2-y1)*yfactor;
	
	var colorRef = new RGBColor;
	colorRef.red = 100;
	colorRef.blue = 200;
	colorRef.green = 100;
	
	var guide = layer.pathItems.rectangle(top,left,width,height);
	guide.strokeColor = colorRef;
	guide.strokeWidth = 3;
}

// get the string between startTag and endTag
function getSubString (data, startTag, endTag)
{
   if( startTag != null) {
	start = data.indexOf(startTag);
	if(start == -1) return null;
	startLen = start+startTag.length;
   } else {
   	startLen = 0;	
   }
   
   if(endTag != null) {
   	end  = data.indexOf(endTag);
   	if(end == -1) return null;
   } else {
   	end = data.length;
   }
   return data.substring(startLen , end);
}